<route lang="json">
{
  "name": "departmentManage",
  "meta": {
    "title": "控制台-部门管理",
    "requiresAuth": true
  }
}
</route>

<script setup lang="ts">
import type { FormInstance } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { onMounted, reactive, ref } from 'vue'
import { createDepartment, deleteDepartment, getDepartmentList, updateDepartment } from '~/api/department'

// 定义部门接口类型
interface Department {
  _id: string
  name: string
  code: string
  parentId?: string | { _id: string, name: string } | null
  sort: number
  status: number
  children?: Department[]
  __v?: number
}

// 部门列表数据
const departmentList = ref<Department[]>([])
const loading = ref(false)

// 表格分页
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
})

// 搜索条件
const searchForm = reactive({
  name: '',
  code: '',
})

// 获取部门列表
async function fetchDepartmentList() {
  loading.value = true
  try {
    const res = await getDepartmentList(pagination.currentPage, pagination.pageSize)
    if (res || res.data) {
      departmentList.value = res || res.data
      pagination.total = res.length || res.data.length
    }
    else {
      departmentList.value = []
      pagination.total = 0
    }
  }
  catch (error) {
    console.error('获取部门列表失败:', error)
    ElMessage.error('获取部门列表失败')
    departmentList.value = []
    pagination.total = 0
  }
  finally {
    loading.value = false
  }
}

// 处理分页变化
function handleCurrentChange(val: number) {
  pagination.currentPage = val
  fetchDepartmentList()
}

function handleSizeChange(val: number) {
  pagination.pageSize = val
  pagination.currentPage = 1
  fetchDepartmentList()
}

// 搜索
function handleSearch() {
  pagination.currentPage = 1
  fetchDepartmentList()
}

// 重置搜索
function resetSearch() {
  searchForm.name = ''
  searchForm.code = ''
  pagination.currentPage = 1
  fetchDepartmentList()
}

// 过滤数据
function getFilteredData() {
  let result = [...departmentList.value]

  if (searchForm.name) {
    result = result.filter(item => item.name.includes(searchForm.name))
  }

  if (searchForm.code) {
    result = result.filter(item => item.code && item.code.includes(searchForm.code))
  }

  return result
}

// 计算当前页的数据
function getCurrentPageData() {
  // 由于后端已经返回了树形结构，我们直接返回顶层部门
  return departmentList.value
}

// 删除部门
function handleDelete(row: Department) {
  if (row.children && row.children.length > 0) {
    ElMessage.warning('该部门下有子部门，不能删除')
    return
  }

  ElMessageBox.confirm('确定要删除该部门吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(async () => {
    try {
      await deleteDepartment(row._id)
      await fetchDepartmentList()
      ElMessage.success('删除成功')
    }
    catch (error) {
      console.error('删除失败:', error)
      ElMessage.error('删除失败')
    }
  }).catch(() => { })
}

// 部门详情对话框
const detailDialogVisible = ref(false)
const currentDepartment = ref<Department | null>(null)

function viewDepartmentDetail(row: Department) {
  currentDepartment.value = { ...row }
  detailDialogVisible.value = true
}

// 添加/编辑部门对话框
const editDialogVisible = ref(false)
const isEdit = ref(false)
const departmentForm = reactive({
  _id: '',
  name: '',
  code: '',
  parentId: '', // 表单中只使用字符串类型
  sort: 1,
  status: 1,
})

// 获取部门树形数据选项
function getDepartmentOptions() {
  const options = [{ id: '', name: '无' }]

  // 递归函数，用于平铺部门树
  function flattenDepartments(departments: Department[], prefix = '') {
    departments.forEach((dept) => {
      options.push({
        id: dept._id,
        name: prefix + dept.name,
      })

      if (dept.children && dept.children.length > 0) {
        flattenDepartments(dept.children, `${prefix + dept.name} / `)
      }
    })
  }

  flattenDepartments(departmentList.value)
  return options
}

// 表单校验规则
const rules = {
  name: [
    { required: true, message: '请输入部门名称', trigger: 'blur' },
    { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
  ],
  code: [
    { required: true, message: '请输入部门编码', trigger: 'blur' },
    { pattern: /^[A-Z0-9]+$/, message: '部门编码只能包含大写字母和数字', trigger: 'blur' },
  ],
}

// 添加部门
function addDepartment() {
  isEdit.value = false
  Object.assign(departmentForm, {
    _id: '',
    name: '',
    code: '',
    parentId: '',
    sort: 1,
    status: 1,
  })
  editDialogVisible.value = true
}

// 编辑部门
function editDepartment(row: Department) {
  isEdit.value = true
  Object.assign(departmentForm, {
    ...row,
    parentId: row.parentId
      ? (typeof row.parentId === 'object' ? row.parentId._id : row.parentId)
      : '',
  })
  editDialogVisible.value = true
}

// 提交表单
const departmentFormRef = ref<FormInstance>()
function submitForm() {
  departmentFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      try {
        // 检查是否形成循环引用
        if (isEdit.value && checkCircularReference(departmentForm._id, departmentForm.parentId)) {
          ElMessage.error('不能选择自己或子部门作为父部门')
          return
        }

        // 准备API所需的数据格式
        const apiData: {
          parentId?: string
          name: string
          code: string
          sort: number
          status: number
        } = {
          name: departmentForm.name,
          code: departmentForm.code,
          sort: departmentForm.sort,
          status: departmentForm.status,
        }

        // 只有当 parentId 有值时才添加到 apiData 中
        if (departmentForm.parentId) {
          apiData.parentId = departmentForm.parentId
        }

        if (isEdit.value) {
          await updateDepartment(departmentForm._id, apiData)
          ElMessage.success('更新成功')
        }
        else {
          const createData = {
            ...apiData,
            parentId: apiData.parentId || '689c544dd955ed8f6638c352',
          }
          await createDepartment(createData)
          ElMessage.success('添加成功')
        }

        editDialogVisible.value = false
        await fetchDepartmentList()
      }
      catch (error) {
        console.error(isEdit.value ? '更新失败:' : '添加失败:', error)
        ElMessage.error(isEdit.value ? '更新失败' : '添加失败')
      }
    }
  })
}

// 检查是否形成循环引用
function checkCircularReference(id: string, parentId: string | undefined): boolean {
  if (id === parentId)
    return true

  const childrenIds = getChildrenIds(id)
  return parentId ? childrenIds.includes(parentId) : false
}

// 获取所有子部门ID
function getChildrenIds(parentId: string): string[] {
  const ids: string[] = []

  function traverse(pid: string) {
    const children = departmentList.value.filter((item) => {
      if (typeof item.parentId === 'object' && item.parentId) {
        return item.parentId._id === pid
      }
      return item.parentId === pid
    })

    children.forEach((child) => {
      ids.push(child._id)
      traverse(child._id)
    })
  }

  traverse(parentId)
  return ids
}

// 页面加载时获取部门列表
onMounted(() => {
  fetchDepartmentList()
})
</script>

<template>
  <div class="department-manage-container">
    <div class="department-header">
      <h2 class="department-title">
        部门管理
      </h2>
      <el-button type="primary" @click="addDepartment">
        添加部门
      </el-button>
    </div>

    <!-- 搜索区域 -->
    <el-card shadow="hover" class="search-card">
      <el-form :model="searchForm" inline>
        <el-form-item label="部门名称">
          <el-input v-model="searchForm.name" placeholder="请输入部门名称" clearable />
        </el-form-item>
        <el-form-item label="部门编码">
          <el-input v-model="searchForm.code" placeholder="请输入部门编码" clearable />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">
            搜索
          </el-button>
          <el-button @click="resetSearch">
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 部门列表 -->
    <el-card shadow="hover" class="department-card">
      <el-table
        v-loading="loading" :data="getCurrentPageData()" row-key="_id" style="width: 100%"
        stripe border :tree-props="{
          children: 'children',
          hasChildren: 'children',
        }"
      >
        <!-- 序号列 -->
        <el-table-column type="index" label="序号" width="60" />

        <!-- 部门名称列 -->
        <el-table-column prop="name" label="部门名称" min-width="120" />

        <!-- 部门编码列 -->
        <el-table-column prop="code" label="部门编码" min-width="100" />

        <!-- 上级部门列 -->
        <el-table-column label="上级部门" min-width="120">
          <template #default="scope">
            <template v-if="scope.row.parentId && typeof scope.row.parentId === 'object'">
              {{ scope.row.parentId.name }}
            </template>
            <template v-else>
              无
            </template>
          </template>
        </el-table-column>

        <!-- 操作列 -->
        <el-table-column label="操作" width="250" fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="viewDepartmentDetail(scope.row)">
              查看
            </el-button>
            <el-button type="primary" link @click="editDepartment(scope.row)">
              编辑
            </el-button>
            <el-button type="danger" link @click="handleDelete(scope.row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
          :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper"
          :total="getFilteredData().length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 部门详情对话框 -->
    <el-dialog v-model="detailDialogVisible" title="部门详情" width="600px" destroy-on-close>
      <div class="department-detail">
        <template v-if="currentDepartment">
          <el-descriptions :column="2" border>
            <el-descriptions-item label="部门名称">
              {{ currentDepartment.name }}
            </el-descriptions-item>
            <el-descriptions-item label="部门编码">
              {{ currentDepartment.code }}
            </el-descriptions-item>
            <el-descriptions-item label="上级部门">
              <template v-if="currentDepartment.parentId && typeof currentDepartment.parentId === 'object'">
                {{ currentDepartment.parentId.name }}
              </template>
              <template v-else>
                无
              </template>
            </el-descriptions-item>
          </el-descriptions>

          <!-- 添加下级部门展示 -->
          <div v-if="currentDepartment.children && currentDepartment.children.length > 0" class="sub-departments">
            <h4 class="sub-title">
              下级部门
            </h4>
            <el-table :data="currentDepartment.children" border style="width: 100%; margin-top: 10px;">
              <el-table-column prop="name" label="部门名称" />
              <el-table-column prop="code" label="部门编码" />
            </el-table>
          </div>
          <div v-else class="no-sub-departments">
            <p>暂无下级部门</p>
          </div>
        </template>
      </div>
    </el-dialog>

    <!-- 添加/编辑部门对话框 -->
    <el-dialog v-model="editDialogVisible" :title="isEdit ? '编辑部门' : '添加部门'" width="600px" destroy-on-close>
      <el-form ref="departmentFormRef" :model="departmentForm" :rules="rules" label-width="100px">
        <el-form-item label="部门名称" prop="name">
          <el-input v-model="departmentForm.name" placeholder="请输入部门名称" />
        </el-form-item>
        <el-form-item label="部门编码" prop="code">
          <el-input v-model="departmentForm.code" placeholder="请输入部门编码" />
        </el-form-item>
        <el-form-item label="上级部门" prop="parentId">
          <el-select v-model="departmentForm.parentId" placeholder="请选择上级部门" style="width: 100%">
            <el-option
              v-for="item in getDepartmentOptions()" :key="item.id" :label="item.name" :value="item.id"
              :disabled="isEdit && item.id === departmentForm._id"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editDialogVisible = false">
          取消
        </el-button>
        <el-button type="primary" @click="submitForm">
          确定
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
* {
  user-select: none;
}

.department-manage-container {
  padding: 20px;

  .department-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;

    .department-title {
      font-size: 20px;
      font-weight: 600;
      margin: 0;
    }
  }

  .search-card {
    margin-bottom: 20px;
  }

  .department-card {
    margin-bottom: 20px;
  }

  .pagination-container {
    margin-top: 20px;
    display: flex;
    justify-content: flex-end;
  }

  .department-detail {
    .sub-title {
      margin-top: 20px;
      margin-bottom: 10px;
      font-weight: 600;
    }

    .no-sub-departments {
      margin-top: 20px;
      color: #909399;
    }
  }
}
</style>
